package com.motong.gongdan.controller.system;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.motong.gongdan.config.CustomCellWriteHandler;
import com.motong.gongdan.config.ResponseData;
import com.motong.gongdan.config.auth.H5LoginToken;
import com.motong.gongdan.config.auth.UserLoginToken;
import com.motong.gongdan.config.interceptor.FormCheckRules;
import com.motong.gongdan.constant.CommonConstant;
import com.motong.gongdan.entity.*;
import com.motong.gongdan.enums.ObjectType;
import com.motong.gongdan.enums.WorkOrderState;
import com.motong.gongdan.service.*;
import com.motong.gongdan.util.*;
import com.motong.gongdan.vo.ExcelModel.MissionExcelModel;
import com.motong.gongdan.vo.ExcelModel.WorkOrderDetailPrintModel;
import com.motong.gongdan.vo.ExcelModel.WorkOrderExcelExport;
import com.motong.gongdan.vo.H5Vo.AppCardHandle;
import com.motong.gongdan.vo.H5Vo.AppCardVo;
import com.motong.gongdan.vo.H5Vo.common.GroupCountVo;
import com.motong.gongdan.vo.H5Vo.common.ListTypeCountVo;
import com.motong.gongdan.vo.H5Vo.mission.query.H5MissionListQuery;
import com.motong.gongdan.vo.H5Vo.mission.vo.H5MissionListVo;
import com.motong.gongdan.vo.H5Vo.workOrder.vo.WorkListMergedConditionVo;
import com.motong.gongdan.vo.resp.*;
import com.motong.gongdan.vo.system.Erp.vo.PushOrderNumVo;
import com.motong.gongdan.vo.system.Produce.query.ReportBadProductQuery;
import com.motong.gongdan.vo.system.common.query.BooleanQuery;
import com.motong.gongdan.vo.system.common.query.IdValueQuery;
import com.motong.gongdan.vo.system.common.query.SecondGroupCondition;
import com.motong.gongdan.vo.system.common.vo.CheckBox;
import com.motong.gongdan.vo.system.otherVo.*;
import com.motong.gongdan.vo.system.processSop.CollectionDataVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.motong.gongdan.constant.CommonConstant.SEARCH_CONDITION_HASH_KEY;
import static com.motong.gongdan.constant.CommonConstant.WORK_REPORT_CONDITION_MERGE_RULE;

/**
 * @author:fff
 * @time:2022/2/25
 */
@Api(value = "生产管理", tags = {"生产管理"})
@RestController
@RequestMapping("/sys/produce/")
public class ProduceController {
    @Resource
    UserService userService;
    @Resource
    WorkOrderService workOrderService;
    @Resource
    ProcessesService processesService;
    @Resource
    ProcessRouteService processRouteService;
    @Resource
    ProductService productService;
    @Resource
    HandleLogService handleLogService;
    @Resource
    MissionService missionService;
    @Resource
    WorkReportService workReportService;
    @Resource
    WagesService wagesService;
    @Resource
    ReportBadProductService reportBadProductService;
    @Resource
    BadProductService badProductService;
    @Resource
    DepartmentsService departmentsService;
    @Resource
    CustomNumberService customNumberService;
    @Resource
    CustomEventService customEventService;
    @Resource
    ScreenPlanService screenPlanService;
    @Resource
    FormTableService formTableService;
    @Resource
    FormTableDetailService formTableDetailService;
    @Resource
    CustomFieldService customFieldService;
    @Resource
    MongoTemplate mongoTemplate;
    @Resource
    UnitService unitService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private AssemblyWorkOrderDetailService assemblyWorkOrderDetailService;
    @Resource
    private StockMsgService stockMsgService;
    @Resource
    private ErpServiceImpl erpService;

    @Value("${excel.printTemplatePath}")
    private String printTemplatePath;

    @UserLoginToken
    @ApiOperation(value = "工单列表")
    @RequestMapping(value = "work_order_list", method = RequestMethod.POST)
    public ResponseData<?> workOrderList(@RequestBody WorkOrderListVo vo) {
        String cacheKey = "workOrder:workOrderList:" + LoginUtil.getLoginUserId();
        if (Objects.nonNull(vo.getSearchOther().get("state"))) {
            redisTemplate.opsForHash().put(SEARCH_CONDITION_HASH_KEY, cacheKey, JSONUtil.toJsonStr(vo.getSearchOther().get("state")));
        } else {
            if (redisTemplate.opsForHash().hasKey(SEARCH_CONDITION_HASH_KEY, cacheKey)) {
                redisTemplate.opsForHash().delete(SEARCH_CONDITION_HASH_KEY, cacheKey);
            }
        }
        //第一次自定义搜索条件
        if (!CollectionUtils.isEmpty(vo.getCustomFieldMap())) {
            List<Integer> includeIds = customFieldService.searchCustomField(vo.getCustomFieldMap(), ObjectType.workOrder.getCode());
            vo.setIds(CollectionUtils.isEmpty(includeIds) ? Collections.singletonList(0) : includeIds);
        }
        //第二次自定义筛选
        WorkOrderListVo secondCondition = Optional.ofNullable(vo.getSearchOther()).orElse(new JSONObject()).toJavaObject(WorkOrderListVo.class);
        if (!CollectionUtils.isEmpty(secondCondition.getCustomFieldMap())) {
            List<Integer> otherIds = customFieldService.searchCustomField(secondCondition.getCustomFieldMap(), ObjectType.workOrder.getCode());
            secondCondition.setIds(CollectionUtils.isEmpty(otherIds) ? Collections.singletonList(0) : otherIds);
        }
        // 二级分组查询条件
        if (Objects.nonNull(vo.getSecondSearchCondition()) && Objects.nonNull(vo.getSecondSearchCondition().getConditionName())) {
            SecondGroupCondition groupCondition = vo.getSecondSearchCondition();
            if ("state".equals(groupCondition.getConditionName())) {
                Integer stateInteger = Integer.valueOf(groupCondition.getConditionValue());
                List<Integer> state = vo.getState();
                vo.setState(CollectionUtils.isEmpty(state) ? Collections.singletonList(stateInteger) : (state.contains(stateInteger) ? state : Collections.singletonList(-1)));
            } else {
                List<Integer> includeIds = customFieldService.searchCustomField(Collections.singletonMap(Integer.valueOf(groupCondition.getConditionName()), groupCondition.getConditionValue()), ObjectType.workOrder.getCode());
                if (CollectionUtils.isEmpty(includeIds)) {
                    vo.setIds(Collections.singletonList(0));
                } else {
                    if (CollectionUtils.isEmpty(vo.getIds())) {
                        vo.setIds(includeIds);
                    } else {
                        List<Integer> intersection = (List<Integer>) CollectionUtil.intersection(vo.getIds(), includeIds);
                        vo.setIds(CollectionUtils.isEmpty(intersection) ? Collections.singletonList(0) : intersection);
                    }
                }
            }
        }
        WorkListMergedConditionVo searchCondition = Optional.ofNullable(BeanMergeUtil.merge(CommonConstant.WORK_ORDER_CONDITION_MERGE_RULE, vo, secondCondition, WorkListMergedConditionVo.class)).orElse(new WorkListMergedConditionVo());
        IPage<WorkOrderResp> data = workOrderService.getList(new Page<>(vo.getPage(), vo.getLimit()), searchCondition, vo.getSortInfoStr());
        WorkOrderRespOther finalData = new WorkOrderRespOther();
        finalData.setData(data);
        List<MenuJsonVo> permissionList = userService.getCurrentUserPermission();
        finalData.setPermissions(permissionList);
        // 二级分组数量统计
        List<GroupCountVo> typeCountData = workOrderService.getSecondGroupTypeCount(vo.getScreenPlanId(), searchCondition);
        finalData.setSecondGroupColumnName(searchCondition.getSecondGroupColumnName());
        finalData.setTypeCountData(typeCountData);
        return ResponseData.success(finalData);
    }


    @UserLoginToken
    @ApiOperation(value = "工单操作")
    @RequestMapping(value = "work_order_handle", method = RequestMethod.POST)
    public ResponseData<?> workOrderHandle(@RequestBody WorkOrderHandleVo vo) {
        Integer userId = LoginUtil.getLoginUserId();
        HandleLog hl = new HandleLog().setType("workOrder").setHandleId(userId).setHandleTime(new Date());
        if (Objects.nonNull(vo.getId())) {
            vo.setProcessIds(null);
            return workOrderService.workOrderEdit(vo, hl, userId);
        } else {
            return workOrderService.workOrderCreate(userId, vo, hl);
        }
    }

    @UserLoginToken
    @ApiOperation(value = "工单删除")
    @RequestMapping(value = "work_order_del", method = RequestMethod.POST)
    public ResponseData workOrderDel(@RequestBody IdVo vo) {
        WorkOrder wo = workOrderService.getById(vo.getId());
        HandleLog hl = new HandleLog();
        hl.setHandleId(LoginUtil.getLoginUserId());
        hl.setHandleTime(new Date());
        hl.setHandleType("删除工单");
        hl.setHandleDetail("删除工单成功，删除的工单编号为【" + wo.getCode() + "】");
        handleLogService.save(hl);
        List<Mission> missions = missionService.list(new QueryWrapper<Mission>().eq("work_order_code", wo.getCode()));
        if (!CollectionUtils.isEmpty(missions)) {
            missions.forEach(m -> {
                missionService.removeById(m.getId());
                MongoUtils.deleteById(m.getId(), mongoTemplate, "mission");

                List<WorkReport> workReports = workReportService.list(new QueryWrapper<WorkReport>().eq("mission_id", m.getId()));
                if (!CollectionUtils.isEmpty(workReports)) {
                    // 同时纠正产品库存
                    if (m.getLast() == 0) {
                        BigDecimal difference = workReports.stream().filter(i -> i.getVerifyState() == 1).map(WorkReport::getGoodProductNumber).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                        productService.rectifyStockByDifference(difference.negate(), m.getProductCode());
                    }
                    // 报工入库删除
                    stockMsgService.removeStockDetailBy(workReports.stream().map(i -> i.getId().toString()).collect(Collectors.toList()));
                    workReports.forEach(w -> {
                        workReportService.removeById(w.getId());
                        // 删除不良品项报工
                        reportBadProductService.remove(new LambdaQueryWrapper<ReportBadProduct>().eq(ReportBadProduct::getWorkReportId, w.getId()));
                        MongoUtils.deleteById(w.getId(), mongoTemplate, "workReport");
                    });
                }
            });
        }
        workOrderService.removeById(vo.getId());
        MongoUtils.deleteById(vo.getId(), mongoTemplate, "workOrder");
        JSONObject jsonObject = (JSONObject) RedisUtil.get("production:day");
        if (jsonObject != null && !jsonObject.isEmpty()) {
            ProductionResp pr = jsonObject.toJavaObject(ProductionResp.class);
            pr.setWorkOrderNumber(pr.getWorkOrderNumber().subtract(BigDecimal.ONE));
            if (wo.getState() != 2 && wo.getState() != 3) {
                if (!TimeUtil.afterNow(wo.getEndTime())) {
                    pr.setNotFinished(pr.getNotFinished().subtract(BigDecimal.ONE));
                }
            }
            JSONObject jo = (JSONObject) JSONObject.toJSON(pr);
            RedisUtil.set("production:day", jo);
        }

        // 同步消除erp
        PushOrderNumVo queryData = formTableService.getErpSalesInfo(wo.getCode());
        if (Objects.nonNull(queryData) && Objects.nonNull(queryData.getRemoteSaleId())) {
            queryData.setStatus(2).setFinishNum(wo.getActualNumber())/*.setSaleDetailId(formTableDetail.getId())*/;
            erpService.pushOrderNum(queryData);
        }

        // 同时删除销售订单中的记录
        formTableDetailService.remove(new LambdaQueryWrapper<FormTableDetail>().eq(FormTableDetail::getWorkOrderCode, wo.getCode()));
        assemblyWorkOrderDetailService.remove(new LambdaQueryWrapper<AssemblyWorkOrderDetail>().eq(AssemblyWorkOrderDetail::getWorkerOrderCode, wo.getCode()));


        return ResponseData.success("success");
    }

    @UserLoginToken
    @ApiOperation(value = "报工删除")
    @RequestMapping(value = "work_report_del", method = RequestMethod.POST)
    public ResponseData workReportDel(@RequestBody IdVo vo) {
        WorkReport workReport = workReportService.getById(vo.getId());
        HandleLog hl = new HandleLog();
        hl.setHandleId(LoginUtil.getLoginUserId());
        hl.setHandleTime(new Date());
        hl.setHandleType("删除报工");
        hl.setHandleDetail("删除报工成功，删除的报工id为【" + workReport.getId() + "】");
        handleLogService.save(hl);
        Mission mission = missionService.getById(workReport.getMissionId());
        if (mission != null) {
            mission.setGoodProductNumber(mission.getGoodProductNumber().subtract(workReport.getGoodProductNumber()));
            mission.setBadProductNumber(mission.getBadProductNumber().subtract(workReport.getBadProductNumber()));
            if (mission.getGoodProductNumber().compareTo(BigDecimal.ZERO) == 0) {
                mission.setProcessState(0);
            } else {
                mission.setProcessState(1);
            }
            missionService.updateById(mission);
            WorkOrder wo = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", mission.getWorkOrderCode()));
            wo.setBadProductNumber(wo.getBadProductNumber().subtract(workReport.getBadProductNumber()));
            if (mission.getLast() == 0) {
                wo.setGoodProductNumber(wo.getGoodProductNumber().subtract(workReport.getGoodProductNumber()));
                wo.setActualNumber(wo.getActualNumber().subtract(workReport.getGoodProductNumber()));
                if (workReport.getVerifyState() == 1 && workReport.getGoodProductNumber().compareTo(BigDecimal.ZERO) != 0) {
                    productService.rectifyStockByDifference(workReport.getGoodProductNumber().negate(), mission.getProductCode());
                }
            }
            workOrderService.updateById(wo);
        }
        List<ReportBadProduct> rbp = reportBadProductService.list(new QueryWrapper<ReportBadProduct>().eq("work_report_id", vo.getId()));
        if (!CollectionUtils.isEmpty(rbp)) {
            reportBadProductService.removeByIds(rbp.stream().map(ReportBadProduct::getId).collect(Collectors.toList()));
        }
        stockMsgService.removeStockDetailBy(Collections.singletonList(vo.getId().toString()));
        workReportService.removeById(vo.getId());
        MongoUtils.deleteById(vo.getId(), mongoTemplate, "workReport");
        return ResponseData.success("success");
    }


    @UserLoginToken
    @ApiOperation(value = "工单导入")
    @RequestMapping(value = "work_order_import", method = RequestMethod.POST)
    public ResponseData workOrderImport(MultipartFile file, Integer type) throws IOException {
        workOrderService.handleImport(file, type);
        return ResponseData.success("请查看导入日志");
    }


    @UserLoginToken
    @ApiOperation(value = "工单导出")
    @RequestMapping(value = "work_order_export", method = RequestMethod.GET)
    public void workOrderExport(HttpServletResponse response) throws IOException {
        List<WorkOrderResp> dataList = workOrderService.getBaseMapper().selectForList();
        List<WorkOrderExcelExport> exportList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(dataList)) {
            AtomicInteger index = new AtomicInteger(1);
            dataList.forEach(d -> {
                WorkOrderExcelExport wee = new WorkOrderExcelExport();
                BeanUtils.copyProperties(d, wee);
                wee.setState(WorkOrderState.getDescByCode(d.getState()));
                wee.setStartTime(TimeUtil.getDateDefaultString(d.getStartTime()));
                wee.setEndTime(TimeUtil.getDateDefaultString(d.getEndTime()));
                User u = userService.getById(d.getCreateId());
                wee.setCreateName(u.getName());
                if (d.getEditId() != null) {
                    User ue = userService.getById(d.getEditId());
                    wee.setEditName(ue.getName());
                }
                wee.setActualStartTime(TimeUtil.getDateDefaultString(d.getActualStartTime()));
                wee.setActualEndTime(TimeUtil.getDateDefaultString(d.getActualEndTime()));
                wee.setCreateTime(TimeUtil.getDateDefaultString(d.getCreateTime()));
                wee.setId(index.getAndIncrement());
                exportList.add(wee);
            });
            String fileName = "exportExcel" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("工单导出数据").registerWriteHandler(new CustomCellWriteHandler()).head(WorkOrderExcelExport.class).doWrite(exportList);
        }
    }


    @UserLoginToken
    @ApiOperation(value = "工单详情")
    @RequestMapping(value = "wo_detail", method = RequestMethod.POST)
    public ResponseData woDetail(@RequestBody IdVo vo) {
        return workOrderService.getDetail(vo);
    }


    @UserLoginToken
    @ApiOperation(value = "操作日志 参数0/1 0:工单/1：报工/ 2:设备  code单条时传报工或工单code")
    @RequestMapping(value = "handle_log_list", method = RequestMethod.POST)
    public ResponseData handleLogList(@RequestBody TypeVo vo) {
        Map<Integer, String> valueModelMap = new HashMap<>(3);
        valueModelMap.put(0, ObjectType.workOrder.getCode());
        valueModelMap.put(1, ObjectType.workReport.getCode());
        valueModelMap.put(2, ObjectType.device.getCode());
        IPage<HandleLog> data = handleLogService.page(new Page<HandleLog>(vo.getPage(), vo.getLimit()), new QueryWrapper<HandleLog>()
                .eq("type", valueModelMap.get(vo.getType()))
                .eq(StringUtil.isNotBlank(vo.getCode()), "handle_code", vo.getCode()));
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            data.getRecords().forEach(d -> {
                if (d.getHandleId() != null) {
                    User user = userService.getById(d.getHandleId());
                    d.setHandleName(user.getName());
                }
            });
        }
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation("任务列表")
    @PostMapping("mission_list")
    public ResponseData<?> missionList(@RequestBody MissionListVo vo) {
        MissionListVo voSearch = Optional.ofNullable(vo.getSearchOther()).orElse(new JSONObject()).toJavaObject(MissionListVo.class);
        //组合查询条件
        MissionListVo voParam = BeanUtil.toBean(vo, MissionListVo.class);
        //自定义字段两次筛选
        if (!CollectionUtils.isEmpty(vo.getCustomFieldMap())) {
            //区分自定义字段的所属模块
            missionService.judgeCustomModel(vo.getCustomFieldMap(), voParam);
        }
        if (!CollectionUtils.isEmpty(voSearch.getCustomFieldMap())) {
            missionService.judgeCustomModel(voSearch.getCustomFieldMap(), voSearch);
        }
        // 二级分组查询条件
        if (Objects.nonNull(vo.getSecondSearchCondition()) && Objects.nonNull(vo.getSecondSearchCondition().getConditionName())) {
            SecondGroupCondition groupCondition = vo.getSecondSearchCondition();
            String conditionName = groupCondition.getConditionName();
            String conditionValue = groupCondition.getConditionValue();
            Map<String, String> missionBaseColumn = ColumnUtils.BASE_COLUMN_EN_CN_MAP.get(ObjectType.mission.getCode());
            //固定字段|自定义字段二级分组
            if (Objects.nonNull(missionBaseColumn.get(conditionName)) || "distributionState".equals(groupCondition.getConditionName()) || "distribution".equals(groupCondition.getConditionName())) {
                MissionListVo secondGroupCondition = new MissionListVo();
                Map<String, String> secondGroupMergeRule = new HashMap<>(1);
                switch (conditionName) {
                    case "processName":
                        secondGroupCondition.setProcessName(conditionValue);
                        secondGroupMergeRule.put("processName", "stringCompareDeprecated");
                        break;
                    case "processState":
                        secondGroupCondition.setProcessState(Collections.singletonList(conditionValue));
                        secondGroupMergeRule.put("processState", "listIntersection");
                        break;
                    case "distributionState":
                        secondGroupCondition.setDistributionState(conditionValue);
                        secondGroupMergeRule.put("distributionState", "stringCompareDeprecated");
                        break;
                    case "distribution":
                        secondGroupCondition.setDistribution(conditionValue);
                        secondGroupMergeRule.put("distribution", "stringCompareDeprecated");
                        break;
                }
                voSearch = Optional.ofNullable(BeanMergeUtil.merge(secondGroupMergeRule, voSearch, secondGroupCondition, MissionListVo.class)).orElse(new MissionListVo());
            } else {
                List<Integer> includeIds = customFieldService.searchCustomField(Collections.singletonMap(Integer.valueOf(groupCondition.getConditionName()), groupCondition.getConditionValue()), ObjectType.mission.getCode());
                if (CollectionUtils.isEmpty(includeIds)) {
                    voSearch.setMissionIds(Collections.singletonList(0));
                } else {
                    if (CollectionUtils.isEmpty(voSearch.getMissionIds())) {
                        voSearch.setMissionIds(includeIds);
                    } else {
                        List<Integer> intersection = (List<Integer>) CollectionUtil.intersection(voSearch.getMissionIds(), includeIds);
                        voSearch.setMissionIds(CollectionUtils.isEmpty(intersection) ? Collections.singletonList(0) : intersection);
                    }
                }
            }
        }
        // 冲突条件合并
        Map<String, String> mergeRule = CommonConstant.MISSION_CONDITION_MERGE_RULE_PC;
        H5MissionListQuery mergeSearchResult = Optional.ofNullable(BeanMergeUtil.merge(mergeRule, voSearch, voParam, H5MissionListQuery.class)).orElse(new H5MissionListQuery());
        // 添加自定义字段条件
        if (Objects.nonNull(mergeSearchResult.getIsDelay())) {
            mergeSearchResult.setDelayTime(DateTime.now().toString());
        }
        Page<Mission> page = new Page<>(Optional.ofNullable(vo.getPage()).orElse(1), Optional.ofNullable(vo.getLimit()).orElse(-1));
        User currentUser = userService.getById(LoginUtil.getLoginUserId());
        if (Objects.nonNull(vo.getScreenPlanId())) {
            ScreenPlan screenPlan = screenPlanService.getById(vo.getScreenPlanId());
            if (StringUtils.hasLength(screenPlan.getScreenCondition())) {
                cn.hutool.json.JSONObject screenCondition = JSONUtil.parseObj(screenPlan.getScreenCondition());
                Object configData = screenCondition.get("configData");
                if (Objects.nonNull(configData)) {
                    List<CustomField> customFields = JSONUtil.toList(configData.toString(), CustomField.class);
                    customFields.forEach(i -> {
                        if ("分配列表".equals(i.getChineseName())) {
                            if (!CollectionUtils.isEmpty(i.getFieldValue())) {
                                String values = i.getFieldValue().stream().map(CheckBox::getValue).collect(Collectors.joining("|"));
                                mergeSearchResult.setDistribution("(^|,)(" + values + ")(,|$))");
                            }
                        }
                    });
                }
            }
        }
        Page<MissionListResp> data = missionService.getH5MissionList(page, mergeSearchResult, currentUser, false);
        // 获取看板二级分组按类型获取数据条数
        List<GroupCountVo> typeCountData = missionService.getSecondGroupTypeCount(vo.getScreenPlanId(), mergeSearchResult, false);
        H5MissionListVo<MissionListResp> finalData = new H5MissionListVo<>(typeCountData, data);
        finalData.setSecondGroupColumnName(mergeSearchResult.getSecondGroupColumnName());
        return ResponseData.success(finalData);
    }

    @UserLoginToken
    @ApiOperation(value = "任务批量修改自定义字段")
    @RequestMapping(value = "edit_custom_fields", method = RequestMethod.POST)
    public ResponseData editCustomFields() {
        List<CustomField> customFieldList = customFieldService.list(new QueryWrapper<CustomField>()
                .eq("field_ascription", "processes")
                .ne("field_type", "relevanceProp")
                .ne("field_type", "upload")
                .ne("field_type", "picture"));
        return ResponseData.success(customFieldList);
    }

    @UserLoginToken
    @ApiOperation(value = "任务修改")
    @RequestMapping(value = "mission_edit", method = RequestMethod.POST)
    public ResponseData missionEdit(@RequestBody MissionEditVo vo) {
        if (StringUtil.isNotBlank(vo.getIds())) {
            AtomicInteger success = new AtomicInteger(0);
            AtomicInteger fail = new AtomicInteger(0);
            Arrays.asList(vo.getIds().split(",")).forEach(s -> {
                Mission mission = missionService.getById(Integer.valueOf(s));
                WorkOrder workOrder = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", mission.getWorkOrderCode()));
                SpringUtil.copyPropertiesIgnoreNull(vo, mission);
                if (StringUtil.isBlank(vo.getDepIds()) && StringUtil.isBlank(vo.getUserIds()) && StringUtil.isBlank(vo.getDistributions())) {
                    if (vo.getPlanedNumber() != null) {
                        mission.setPlanedNumber(vo.getPlanedNumber());
                        BigDecimal woPlanedNumber = workOrder.getPlanedNumber();
                        BigDecimal miPlanedNumber = mission.getPlanedNumber();
                        mission.setRate(miPlanedNumber.divide(woPlanedNumber, 6, BigDecimal.ROUND_HALF_UP));
                        success.getAndIncrement();
                    }
                    if (vo.getRate() != null) {
                        BigDecimal woPlanedNumber = workOrder.getPlanedNumber();
                        BigDecimal misPlanedNumber = woPlanedNumber.multiply(vo.getRate()).setScale(2, BigDecimal.ROUND_HALF_UP);
                        mission.setPlanedNumber(misPlanedNumber);
                        success.getAndIncrement();
                    }
                } else {
                    Processes processes = processesService.getOne(new QueryWrapper<Processes>().eq("code", mission.getProcessCode()));

                    // 如果是自己创建或所有或在给定部门下则为true
                    User currentUser = userService.getById(LoginUtil.getLoginUserId());
                    boolean havePermission = false;
                    //部门权限判断
                    if (StringUtils.hasLength(processes.getPermissionsDep()) && StringUtils.hasLength(currentUser.getDepId())) {
                        havePermission = CollectionUtils.containsAny(Arrays.asList(processes.getPermissionsDep().split(",")), Arrays.asList(currentUser.getDepId().split(",")));
                    }
                    //用户权限判断
                    if (StringUtils.hasLength(processes.getPermissionsName()) && !havePermission) {
                        havePermission = CollectionUtils.containsAny(Arrays.asList(processes.getPermissionsName().split(",")), Arrays.asList(currentUser.getName(), "所有人"));
                    }

                    if (StringUtil.isNotBlank(processes.getPermissionsName()) && havePermission) {
                        List<String> ids = new ArrayList<>();
                        if (vo.getDistributions().equals("0")) {
                            if (processes != null && StringUtil.isNotBlank(processes.getPermissions())) {
                                ids.addAll(Arrays.asList(processes.getPermissions().split(",")));
                            }
                        } else if (vo.getDistributions().equals("-1")) {
                            List<User> userList = userService.list(new QueryWrapper<User>().eq("state", 0)
                                    .eq("factory_id", LoginUtil.getLoginUserFactory()).eq("virtual_type", 0));
                            ids.addAll(userList.stream().map(User::getId).map(m -> m + "").collect(Collectors.toList()));
                        } else if (StringUtil.isBlank(vo.getDistributions())) {
                            if (StringUtil.isNotBlank(vo.getDepIds())) {
                                List<Departments> list = departmentsService.listByIds(Arrays.asList(vo.getDepIds().split(",")));
                                list.forEach(l -> {
                                    List<String> sList = Arrays.asList(l.getIds().split(","));
                                    ids.addAll(sList);
                                });
                            }
                            if (StringUtil.isNotBlank(vo.getUserIds())) {
                                List<User> userList = userService.listByIds(Arrays.asList(vo.getUserIds().split(",")));
                                ids.addAll(userList.stream().map(User::getId).map(u1 -> u1 + "").collect(Collectors.toList()));
                            }
                        }
                        mission.setDistributionList(String.join(",", ids));
                    } else {
                        fail.getAndIncrement();
                    }
                }
                if (mission.getPlanedNumber().compareTo(mission.getGoodProductNumber() == null ? BigDecimal.ZERO : mission.getGoodProductNumber()) < 1) {
                    mission.setProcessState(2);
                }
                if (!CollectionUtils.isEmpty(vo.getCustomFieldVos()) || (Objects.nonNull(vo.getCustomFieldVos()) && vo.getCustomFieldVos().size() == 0)) {
                    mission.setProcessOther(customFieldService.handleObjectCreateOrEdit(vo.getCustomFieldVos()).toJSONString());
                    missionService.cacheCustomToMongo(mission);
                }
                if (!CollectionUtils.isEmpty(vo.getProcessCollectionData())) {
                    mission.setProcessCollectionData(JSONArray.parseArray(JSON.toJSONString(vo.getProcessCollectionData())).toJSONString());
                }
                if (Objects.nonNull(vo.getUserIds()) && vo.getUserIds().isEmpty() && Objects.nonNull(vo.getDistributions()) && vo.getDistributions().isEmpty()) {
                    mission.setDistributionList("");
                }
                missionService.updateById(mission);
//                success.getAndIncrement();
            });
            HandleNumResp hnr = new HandleNumResp();
            hnr.setTotal(vo.getIds().split(",").length);
            hnr.setSuccessNum(success.get());
            hnr.setFailNum(fail.get());
            return ResponseData.success(hnr);
        } else {
            Mission mission = missionService.getById(vo.getId());
            if (!CollectionUtils.isEmpty(vo.getCustomFieldVos()) || (Objects.nonNull(vo.getCustomFieldVos()) && vo.getCustomFieldVos().isEmpty())) {
                mission.setProcessOther(customFieldService.handleObjectCreateOrEdit(vo.getCustomFieldVos()).toJSONString());
                missionService.cacheCustomToMongo(mission);
            }
            if (!CollectionUtils.isEmpty(vo.getProcessCollectionData())) {
                mission.setProcessCollectionData(JSONArray.parseArray(JSON.toJSONString(vo.getProcessCollectionData())).toJSONString());
            }
            if (Objects.nonNull(vo.getRate()) && Objects.nonNull(vo.getPlanedNumber())) {
                mission.setRate(vo.getRate()).setPlanedNumber(vo.getPlanedNumber());
            }
            missionService.updateById(mission);
            Processes processes = processesService.getOne(new QueryWrapper<Processes>().eq("code", mission.getProcessCode()));
            mission.setProcessName(processes.getName());
            customEventService.sendCustomEventMsg(1, 0, 1, null, mission, null);
        }
        return ResponseData.success("success");
    }

    @UserLoginToken
    @ApiOperation(value = "任务详情")
    @RequestMapping(value = "mission_detail", method = RequestMethod.POST)
    public ResponseData missionDetail(@RequestBody IdVo vo) {
        MissionListResp mlr = missionService.getBaseMapper().getMissionDetail(new QueryWrapper<MissionListResp>().eq("m.id", vo.getId()));
        if (StringUtil.isNotBlank(mlr.getProcessPermissions())) {
            handleUserIdsToName(mlr);
        }
        Processes processes = processesService.getOne(new QueryWrapper<Processes>().eq("code", mlr.getProcessCode()));
        if (StringUtil.isNotBlank(mlr.getProcessOther())) {
            mlr.setCustomFieldVos(customFieldService.handleCustomFieldForList(mlr.getProcessOther()));
        }
        if (StringUtil.isNotBlank(mlr.getProcessCollectionData())) {
            mlr.setProcessCollectionDataList(JSONArray.parseArray(mlr.getProcessCollectionData()).toJavaList(CollectionDataVo.class));
        } else {
            if (StringUtil.isNotBlank(processes.getCollectionData())) {
                mlr.setProcessCollectionDataList(JSONArray.parseArray(processes.getCollectionData()).toJavaList(CollectionDataVo.class));
            }
        }
        return ResponseData.success(mlr);
    }

    @UserLoginToken
    @ApiOperation(value = "任务删除")
    @RequestMapping(value = "mission_del", method = RequestMethod.POST)
    public ResponseData missionDel(@RequestBody IdVo vo) {
        Mission mission = missionService.getById(vo.getId());
        WorkOrder workOrder = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", mission.getWorkOrderCode()));
        if (workOrder != null && StringUtil.isNotBlank(workOrder.getProcessId())) {
            Processes processes = processesService.getOne(new QueryWrapper<Processes>().eq("code", mission.getProcessCode()));
            List<String> processIds = new ArrayList<>(Arrays.asList(workOrder.getProcessId().split(",")));
            boolean exist = processIds.stream().anyMatch(p -> p.equals(processes.getId().toString()));
            List<WorkReport> list = workReportService.list(new QueryWrapper<WorkReport>().eq("mission_id", mission.getId()));
            if (exist) {
                processIds.removeIf(processes.getId().toString()::equals);
                workOrder.setProcessId(processIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
                if (mission.getLast() == 0) {
                    workOrder.setGoodProductNumber(workOrder.getGoodProductNumber().subtract(mission.getGoodProductNumber()));
                    //纠正产品库存
                    BigDecimal difference = list.stream().filter(i -> i.getVerifyState() == 1).map(WorkReport::getGoodProductNumber).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                    productService.rectifyStockByDifference(difference.negate(), mission.getProductCode());
                }
                workOrderService.updateById(workOrder);
                if (StringUtil.isBlank(workOrder.getProcessId())) {
                    workOrderService.removeById(workOrder.getId());
                    // 同时删除销售订单中的记录
                    formTableDetailService.remove(new LambdaQueryWrapper<FormTableDetail>().eq(FormTableDetail::getWorkOrderCode, workOrder.getCode()));
                    // 同时删除装配工单中的记录
                    assemblyWorkOrderDetailService.remove(new LambdaQueryWrapper<AssemblyWorkOrderDetail>().eq(AssemblyWorkOrderDetail::getWorkerOrderCode, workOrder.getCode()));
                }
            }
            if (!CollectionUtils.isEmpty(list)) {
                List<Integer> workReportIds = list.stream().map(WorkReport::getId).collect(Collectors.toList());
                stockMsgService.removeStockDetailBy(workReportIds.stream().map(Object::toString).collect(Collectors.toList()));
                workReportService.removeByIds(workReportIds);
            }
        }
        missionService.removeById(mission.getId());
        MongoUtils.deleteById(vo.getId(), mongoTemplate, "mission");
        customEventService.sendCustomEventMsg(1, 0, 2, null, mission, null);
        return ResponseData.success("success");
    }

    @UserLoginToken
    @ApiOperation(value = "任务导出")
    @RequestMapping(value = "mission_export", method = RequestMethod.GET)
    public void missionExport(HttpServletResponse response) throws IOException {
        List<MissionExcelModel> exportList = new ArrayList<>();
        List<MissionListResp> dataList = missionService.getBaseMapper().getListO(new QueryWrapper<MissionListResp>().orderByDesc("m.id"));
        if (!CollectionUtils.isEmpty(dataList)) {
            AtomicInteger index = new AtomicInteger(1);
            dataList.forEach(data -> {
                handleUserIdsToName(data);
                String state = "";
                if (data.getProcessState() != null) {
                    if (data.getProcessState() == 0) {
                        state = "未开始";
                    } else if (data.getProcessState() == 1) {
                        state = "执行中";
                    } else {
                        state = "已结束";
                    }
                }
                MissionExcelModel mem = new MissionExcelModel();
                BeanUtils.copyProperties(data, mem);
                mem.setProcessState(state);
                mem.setId(index.getAndIncrement());
                exportList.add(mem);
            });
            String fileName = "exportExcel" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("任务导出数据").registerWriteHandler(new CustomCellWriteHandler()).head(MissionExcelModel.class).doWrite(exportList);
        }
    }


    @UserLoginToken
    @ApiOperation(value = "修改任务状态")
    @PostMapping(value = "updateMissionState")
    public ResponseData<String> updateMissionState(@RequestBody IdValueQuery query) {
        if (!CollectionUtils.isEmpty(query.getIdList()) && Objects.nonNull(query.getValue())) {
            List<Mission> missions = missionService.listByIds(query.getIdList());
            List<Mission> newMission = new ArrayList<>(missions.size());
            missions.forEach(i -> {
                Mission mission = new Mission().setId(i.getId()).setDistributionList(i.getDistributionList()).setProcessState(Convert.toInt(query.getValue()));
                missionService.changeStatus(mission, i);
                newMission.add(mission);
            });
            if (!CollectionUtils.isEmpty(newMission)) {
                missionService.updateBatchById(newMission);
            }
        }
        return ResponseData.success("修改成功!");
    }

    private void handleUserIdsToName(MissionListResp data) {
        if (StringUtil.isNotBlank(data.getProcessPermissions())) {
            if (StringUtils.hasLength(data.getPermissionsName()) && CollectionUtils.contains(Arrays.asList(data.getPermissionsName().split(",")).iterator(), "所有人")) {
                data.setProcessPermissions("所有人");
            } else {
                List<String> ids = Arrays.asList(data.getProcessPermissions().split(","));
                String userName = userService.listByIds(ids).stream().map(User::getName).collect(Collectors.joining(","));
                data.setProcessPermissions(userName);
            }
        }
    }


    @UserLoginToken
    @ApiOperation(value = "报工列表")
    @PostMapping("work_report_list")
    public ResponseData<ListTypeCountVo<WorkReportListResp>> workReportList(@RequestBody WorkReportListVo vo) {
        //第一次自定义搜索条件
        if (!CollectionUtils.isEmpty(vo.getCustomFieldSearch())) {
            List<Integer> includeIds = customFieldService.searchCustomField(vo.getCustomFieldSearch(), ObjectType.workReport.getCode());
            vo.setIds(CollectionUtils.isEmpty(includeIds) ? Collections.singletonList(0) : includeIds);
        }
        //第二次自定义筛选
        WorkReportListVo voSearch = Optional.ofNullable(vo.getSearchOther()).orElse(new JSONObject()).toJavaObject(WorkReportListVo.class);
        if (!CollectionUtils.isEmpty(voSearch.getCustomFieldSearch())) {
            List<Integer> otherIds = customFieldService.searchCustomField(voSearch.getCustomFieldSearch(), ObjectType.workReport.getCode());
            voSearch.setIds(CollectionUtils.isEmpty(otherIds) ? Collections.singletonList(0) : otherIds);
        }
        // 二级分组查询条件
        if (Objects.nonNull(vo.getSecondSearchCondition()) && Objects.nonNull(vo.getSecondSearchCondition().getConditionName())) {
            SecondGroupCondition groupCondition = vo.getSecondSearchCondition();
            Map<String, String> workReportColumn = ColumnUtils.BASE_COLUMN_EN_CN_MAP.get(ObjectType.workReport.getCode());
            String conditionName = groupCondition.getConditionName();
            String conditionValue = groupCondition.getConditionValue();
            //固定字段|自定义字段二级分组
            if (Objects.nonNull(workReportColumn.get(conditionName))) {
                WorkReportListVo secondGroupCondition = new WorkReportListVo();
                Map<String, String> secondGroupMergeRule = new HashMap<>(1);
                // 固定字段二级分组查询
                secondGroupMergeRule.put(conditionName, "stringCompareDeprecated");
                switch (conditionName) {
                    case "verifyState":
                        secondGroupCondition.setVerifyState(conditionValue);
                        break;
                    case "pricingMethod":
                        secondGroupCondition.setPricingMethod(conditionValue);
                        break;
                }
                voSearch = Optional.ofNullable(BeanMergeUtil.merge(secondGroupMergeRule, voSearch, secondGroupCondition, WorkReportListVo.class)).orElse(new WorkReportListVo());
            } else {
                List<Integer> includeIds = customFieldService.searchCustomField(Collections.singletonMap(Integer.valueOf(groupCondition.getConditionName()), groupCondition.getConditionValue()), ObjectType.workReport.getCode());
                if (CollectionUtils.isEmpty(includeIds)) {
                    vo.setIds(Collections.singletonList(0));
                } else {
                    if (CollectionUtils.isEmpty(vo.getIds())) {
                        vo.setIds(includeIds);
                    } else {
                        List<Integer> intersection = (List<Integer>) CollectionUtil.intersection(vo.getIds(), includeIds);
                        vo.setIds(CollectionUtils.isEmpty(intersection) ? Collections.singletonList(0) : intersection);
                    }
                }
            }
        }
        // 冲突条件合并
        Map<String, String> mergeRule = WORK_REPORT_CONDITION_MERGE_RULE;
        WorkReportListVo mergeSearchResult = Optional.ofNullable(BeanMergeUtil.merge(mergeRule, vo, voSearch, WorkReportListVo.class)).orElse(new WorkReportListVo());
        // 添加自定义字段条件
        Page<WorkReport> page = new Page<>(Optional.ofNullable(vo.getPage()).orElse(1), Optional.ofNullable(vo.getLimit()).orElse(-1));
        Page<WorkReportListResp> data = workReportService.getWorkReportList(page, mergeSearchResult);
        // 获取看板二级分组按类型获取数据条数
        List<GroupCountVo> typeCountData = workReportService.getSecondGroupTypeCount(vo.getScreenPlanId(), mergeSearchResult);
        ListTypeCountVo<WorkReportListResp> finalData = new ListTypeCountVo<>(typeCountData, data);
        finalData.setSecondGroupColumnName(mergeSearchResult.getSecondGroupColumnName());
        return ResponseData.success(finalData);
    }


    @UserLoginToken
    @ApiOperation(value = "报工创建内工单编号下拉框")
    @RequestMapping(value = "wr_work_order", method = RequestMethod.POST)
    public ResponseData woWorkOrder(@RequestBody SearchVo vo) {
        Integer userId = LoginUtil.getLoginUserId();
        List<Processes> list = processesService.getBaseMapper().getProcesses(userId);
        List<WorkOrder> newList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            List<WorkOrder> workOrderList = new ArrayList<>();
            list.forEach(l -> {
                List<WorkOrder> wo = workOrderService.getBaseMapper().getWorkOrderByProcessId(l.getId(), vo.getSearch());
                if (!CollectionUtils.isEmpty(wo)) {
                    workOrderList.addAll(wo);
                }
            });
            if (!CollectionUtils.isEmpty(workOrderList)) {
                newList = workOrderList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WorkOrder::getCode))), ArrayList::new));
                String processCodes = list.stream().map(Processes::getCode).collect(Collectors.joining(","));

                if (!CollectionUtils.isEmpty(newList)) {
                    newList.forEach(n -> {
                        if (n.getProductId() != null) {
                            Product product = productService.getById(n.getProductId());
                            n.setProduct(product);
                        }
                        if (StringUtil.isNotBlank(n.getProcessId())) {
                            IPage<MissionListResp> data = missionService.getBaseMapper().getList(new Page<MissionListResp>(0, 100),
                                    new QueryWrapper<MissionListResp>().eq("m.work_order_code", n.getCode())
                                            .last("AND  FIND_IN_SET(m.process_code,'" + processCodes + "')  order by field(m.last, 0), m.last"));
                            n.setProcessesList(data.getRecords());
                        }
                    });
                }
                return ResponseData.success(newList);
            }
        }
        return ResponseData.success(newList);
    }

    @UserLoginToken
    @ApiOperation(value = "报工创建内工序下拉框 参数传code 工单code")
    @RequestMapping(value = "wr_process", method = RequestMethod.POST)
    public ResponseData wrProcess(@RequestBody NormalVo vo) {
        WorkOrder wo = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", vo.getCode()));
        if (wo != null && StringUtil.isNotBlank(wo.getProcessId())) {
            List<Mission> missionList = missionService.list(new QueryWrapper<Mission>().eq("work_order_code", wo.getCode()));
            List<Mission> missions = new ArrayList<>();
            if (!CollectionUtils.isEmpty(missionList)) {
                missionList.forEach(m -> {
                    Processes p = processesService.getOne(new QueryWrapper<Processes>().eq("code", m.getProcessCode()));
                    if (p != null) {
                        m.setProcessName(p.getName());
                        missions.add(m);
                    } else {
                        Mission mission = missionService.getOne(new QueryWrapper<Mission>().eq("work_order_code", m.getWorkOrderCode()).eq("last", m.getLast() + 1));
                        if (mission == null) {
                            mission = missionService.getOne(new QueryWrapper<Mission>().eq("work_order_code", m.getWorkOrderCode()).eq("last", 0));
                        }
                        Processes p1 = processesService.getOne(new QueryWrapper<Processes>().eq("code", mission.getProcessCode()));
                        if (p1 != null) {
                            mission.setProcessName(p1.getName());
                            missions.add(mission);
                        }
                    }
                });
                return ResponseData.success(missions);
            }
        }
        return ResponseData.fail(500, "暂无数据");

    }


    @FormCheckRules
    @UserLoginToken
    @ApiOperation(value = "报工操作")
    @RequestMapping(value = "work_report_handle", method = RequestMethod.POST)
    @Transactional
    public ResponseData workReportHandle(@RequestBody WorkReportHandleVo vo) {
        Mission mission = null;
        if (vo.getId() == null) {
            mission = missionService.getById(vo.getMissionId());
        } else {
            WorkReport workReport = workReportService.getById(vo.getId());
            mission = missionService.getById(workReport.getMissionId());
        }
        HandleLog hl = new HandleLog();
        hl.setHandleId(LoginUtil.getLoginUserId());
        hl.setType("workReport");
        hl.setHandleTime(new Date());
        if (mission != null) {
            return workReportService.handleWorkReport(hl, mission, vo);
        }
        return ResponseData.fail(500, "操作失败");
    }


    @UserLoginToken
    @ApiOperation(value = "报工生产人员")
    @RequestMapping(value = "report_produce_user", method = RequestMethod.POST)
    public ResponseData reportProduceUser(@RequestBody WorkReportHandleVo vo) {
        if (StringUtil.isNotBlank(vo.getProcessCode())) {
            Processes processes = processesService.getOne(new QueryWrapper<Processes>().eq("code", vo.getProcessCode()));
            List<User> list = userService.getBaseMapper().getUserNameAndId(new QueryWrapper<User>().in("id", Arrays.asList(processes.getPermissions().split(","))));
            return ResponseData.success(list);
        }
        return null;
    }

    @UserLoginToken
    @ApiOperation(value = "报工绩效")
    @RequestMapping(value = "wr_wages", method = RequestMethod.POST)
    public ResponseData wrWages(@RequestBody WrWagesVo vo) {
        BigDecimal wages = BigDecimal.ZERO;
        if (vo.getPricing() == 0) {
            List<Wages> wagesList = wagesService.list(new QueryWrapper<Wages>().eq("product_code", vo.getProductCode()).eq("pricing", 0).eq(vo.getProcessId() != null, "process_id", vo.getProcessId()));
            if (!CollectionUtils.isEmpty(wagesList)) {
                Wages w = wagesList.get(0);
                wages = w.getUnitPrice().multiply(vo.getGoodProductNumber()).setScale(2, RoundingMode.DOWN);
                w.setEstimateWage(wages);
                return ResponseData.success(w);
            } else {
                return ResponseData.fail(500, "未找到对应产品绩效工资配置");
            }
        } else {
            List<Wages> wagesList = wagesService.list(new QueryWrapper<Wages>().eq("product_code", vo.getProductCode()).eq("pricing", 1).eq(vo.getProcessId() != null, "process_id", vo.getProcessId()));
            if (!CollectionUtils.isEmpty(wagesList)) {
                Wages w = wagesList.get(0);
                Double minutes = TimeUtil.getDateSubMinutes(TimeUtil.getDateDefaultString(vo.getStartTime()), TimeUtil.getDateDefaultString(vo.getEndTime()));
                BigDecimal minPrice = w.getUnitPrice().divide(BigDecimal.valueOf(60), 2, RoundingMode.DOWN);
                wages = minPrice.multiply(BigDecimal.valueOf(minutes)).setScale(2, RoundingMode.DOWN);
                w.setEstimateWage(wages);
                return ResponseData.success(w);
            } else {
                return ResponseData.fail(500, "未找到对应产品绩效工资配置");
            }
        }
    }


    @UserLoginToken
    @ApiOperation(value = "报工导出")
    @RequestMapping(value = "work_report_export", method = RequestMethod.GET)
    public void workReportExport(HttpServletResponse response) throws IOException {
        IPage<WorkReportListResp> data = workReportService.getBaseMapper().getList(new Page(1, 100), null, null, null, null, null, null, null, null,
                null, null, null, null, null, null, null, null, null);
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            List<WorkReportListResp> list = data.getRecords();
            if (!CollectionUtils.isEmpty(list)) {
                AtomicInteger index = new AtomicInteger(1);
                list.forEach(l -> {
                    l.setId(index.getAndIncrement());
                });
            }
            String fileName = "exportExcel" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("报工导出数据").registerWriteHandler(new CustomCellWriteHandler()).head(WorkReportListResp.class).doWrite(list);
        }
    }

    @UserLoginToken
    @ApiOperation(value = "报工添加获取生产人员")
    @RequestMapping(value = "work_report_add_get", method = RequestMethod.POST)
    public ResponseData workReportAddGet(@RequestBody NormalVo vo) {
        if (vo.getCode() != null) {
            Processes processes = processesService.getOne(new QueryWrapper<Processes>().eq("code", vo.getCode()));
            if (StringUtil.isNotBlank(processes.getPermissions()) && StringUtils.hasLength(processes.getPermissionsName())) {
                List<String> userIds = Arrays.asList(processes.getPermissions().split(","));
                LambdaQueryWrapper<User> userQW = new LambdaQueryWrapper<User>()
                        .in(!processes.getPermissionsName().contains("所有人"), User::getId, userIds).eq(User::getState, 0);
                List<User> userList = userService.list(userQW);
                List<User> uList = new ArrayList<>();
                userList.forEach(u -> {
                    User user = new User();
                    user.setId(u.getId());
                    user.setName(u.getName());
                    uList.add(user);
                });
                return ResponseData.success(uList);
            } else {
                return ResponseData.fail(500, "工序未配置报工人员权限");
            }
        }
        return ResponseData.fail(500, "请选择工序");
    }

    @UserLoginToken
    @ApiOperation(value = "报工获取不良品项")
    @PostMapping("report_bad_product")
    public ResponseData<?> reportBadProduct(@RequestBody ReportBadProductQuery vo) {
        List<String> ids = null;
        if (StringUtils.hasLength(vo.getProcessCode())) {
            Processes process = processesService.getOne(new LambdaQueryWrapper<Processes>().eq(Processes::getCode, vo.getProcessCode()));
            if (Objects.nonNull(process) && StringUtils.hasLength(process.getBadProduct())) {
                ids = new ArrayList<>(Arrays.asList(process.getBadProduct().split(",")));
            }
        }
        List<BadProduct> list = badProductService.list(new QueryWrapper<BadProduct>()
                .in(!CollectionUtils.isEmpty(ids), "id", ids)
                .like(StringUtil.isNotBlank(vo.getName()), "name", vo.getName()));
        return ResponseData.success(list);
    }

    @UserLoginToken
    @ApiOperation(value = "报工详情")
    @RequestMapping(value = "report_detail", method = RequestMethod.POST)
    public ResponseData reportDetail(@RequestBody IdVo vo) {
        if (vo.getId() != null) {
            return ResponseData.success(workReportService.getReportDetail(vo.getId()));
        }
        return ResponseData.fail(500, "fail");
    }

    @UserLoginToken
    @ApiOperation(value = "报工导入")
    @RequestMapping(value = "work_report_import", method = RequestMethod.POST)
    public ResponseData workReportImport(MultipartFile file) throws IOException, NoSuchFieldException, IllegalAccessException, ExecutionException, InterruptedException {
        workReportService.handleImport(file);
        return ResponseData.success("请查看导入日志");
    }


    @UserLoginToken
    @ApiOperation(value = "工单流转卡打印")
    @RequestMapping(value = "workOrderPrint", method = RequestMethod.GET)
    public void workOrderPrint(HttpServletResponse response, String ids) throws IOException {

        String[] split = ids.split(",");
        ArrayList<Integer> integers = new ArrayList<>();
        for (String s : split) {
            integers.add(Integer.valueOf(s));
        }

        //模板位置
        String templateFileName = printTemplatePath.concat("工单流转卡.xlsx");
        //保存位置
        String fileName = "/service/excel/print/" + "simpleFill" + System.currentTimeMillis() + ".xlsx";
        //模板位置
        //保存位置
        String newFileName = "/service/excel/print/" + "工单" + System.currentTimeMillis() + ".xlsx";
//        String newFileName = "/Users/fff/Downloads/" + "工单流转卡" + System.currentTimeMillis() + ".xlsx";
        File templateFile = new File(templateFileName);
        FileInputStream fis = new FileInputStream(templateFile);
        XSSFWorkbook workbook = new XSSFWorkbook(fis);
        for (int i = 0; i < integers.size() - 1; i++) {
            workbook.cloneSheet(1);
        }
        FileOutputStream out = new FileOutputStream(new File(fileName));
        out.flush();
        workbook.write(out);
        out.close();
        ExcelWriter excelWriter = EasyExcel.write(newFileName).withTemplate(fileName).build();

        for (int i = 0; i < integers.size(); i++) {
            WorkOrderDetailPrintModel wo = workOrderService.getBaseMapper().getModelData(integers.get(i));

            if (wo.getState().equals("0")) {
                wo.setState("未开始");
            } else if (wo.getState().equals("1")) {
                wo.setState("执行中");
            } else if (wo.getState().equals("2")) {
                wo.setState("已结束");
            } else {
                wo.setState("已取消");
            }
            Integer loginUserId = LoginUtil.getLoginUserId();
            User user = userService.getById(loginUserId);
            wo.setHandleName(user.getName());
            wo.setHandleTime(new Date());
            WriteSheet writeSheet = EasyExcel.writerSheet(1 + i).build();
            writeSheet.setSheetNo(i + 1);
            writeSheet.setSheetName("工单流转卡" + (i + 1));
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            excelWriter.fill(wo, writeSheet);

            List<Mission> missions = missionService.list(new QueryWrapper<Mission>().eq("work_order_code", wo.getWorkOrderCode()));
            if (!CollectionUtils.isEmpty(missions)) {
                missions.forEach(m -> {
                    Processes process = processesService.getOne(new QueryWrapper<Processes>().eq("code", m.getProcessCode()));
                    if (process != null) {
                        m.setProcessName(process.getName());
                        m.setUnFinishNum(m.getPlanedNumber().subtract(m.getGoodProductNumber()));
                    }
                });
                excelWriter.fill(missions, fillConfig, writeSheet);
            }

        }
        int flag = 0;
        if (integers.size() > 1) {
            Workbook sourceWorkbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
            Workbook targeWorkbook = new SXSSFWorkbook();
            Workbook workbook1 = mergeWorkSheet(targeWorkbook, sourceWorkbook, integers.size(), flag);
            excelWriter.writeContext().writeWorkbookHolder().setWorkbook(workbook1);
        }

        excelWriter.finish();
        File file = new File(newFileName);
        OwnUtil.fileToResponse(file, response);
        file.delete();

    }


    public Workbook mergeWorkSheet(Workbook targetWorkbook, Workbook sourceWorkbook, int size, int flag) {
        try {
            //表合并后新表名称
            Sheet targetSheet;
            if (flag == 0) {
                targetSheet = targetWorkbook.createSheet("工单流转卡");

            } else {
                targetSheet = targetWorkbook.createSheet("工单二维码");
            }
            int secondSourceSheetLen = 0;
            SXSSFWorkbook sw = (SXSSFWorkbook) sourceWorkbook;
            for (int i = 1; i < size + 1; i++) {
                XSSFSheet sheetAt1 = sw.getXSSFWorkbook().getSheetAt(i);
                POIUtil.copySheet(targetSheet, sheetAt1, targetWorkbook, sourceWorkbook, secondSourceSheetLen);
                secondSourceSheetLen += sheetAt1.getPhysicalNumberOfRows();
            }
            return targetWorkbook;
        } catch (Exception e) {
            return null;
        }
    }

    @UserLoginToken
    @ApiOperation(value = "工单二维码")
    @RequestMapping(value = "workOrderQr", method = RequestMethod.GET)
    public void workOrderQr(HttpServletResponse response, String ids) throws IOException {

        String[] split = ids.split(",");
        ArrayList<Integer> integers = new ArrayList<>();
        for (String s : split) {
            integers.add(Integer.valueOf(s));
        }

        String templateFileName = printTemplatePath.concat("工单二维码.xlsx");
        String fileName = "/service/excel/print/" + "simpleFill" + System.currentTimeMillis() + ".xlsx";
       /* String templateFileName = "C:\\Users\\91045\\Desktop\\工单二维码.xlsx";
        String fileName = "C:\\Users\\91045\\Desktop\\" + "simpleFill" + System.currentTimeMillis() + ".xlsx";
*/
        String newFileName = "/service/excel/print/" + "工单二维码" + System.currentTimeMillis() + ".xlsx";

        File templateFile = new File(templateFileName);
        FileInputStream fis = new FileInputStream(templateFile);
        XSSFWorkbook workbook = new XSSFWorkbook(fis);
        for (int i = 0; i < integers.size() - 1; i++) {
            workbook.cloneSheet(1);
        }
        FileOutputStream out = new FileOutputStream(new File(fileName));
        out.flush();
        workbook.write(out);
        out.close();
        ExcelWriter excelWriter = EasyExcel.write(newFileName).withTemplate(fileName).build();
        for (int i = 0; i < integers.size(); i++) {
            WorkOrderDetailPrintModel wo = workOrderService.getBaseMapper().getModelData(integers.get(i));
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            writeSheet.setSheetNo(i + 1);

            excelWriter.fill(wo, writeSheet);
        }

        int flag = 1;
        if (integers.size() > 1) {
            Workbook sourceWorkbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
            Workbook targeWorkbook = new SXSSFWorkbook();
            Workbook workbook1 = mergeWorkSheet(targeWorkbook, sourceWorkbook, integers.size(), flag);
            excelWriter.writeContext().writeWorkbookHolder().setWorkbook(workbook1);
        }

        excelWriter.finish();
        File file = new File(newFileName);
        OwnUtil.fileToResponse(file, response);
        file.delete();

    }

    @UserLoginToken
    @ApiOperation(value = "工单列表打印")
    @RequestMapping(value = "workOrderList", method = RequestMethod.GET)
    public void workOrderList(HttpServletResponse response, String ids) throws IOException {

        String[] split = ids.split(",");
        ArrayList<Integer> integers = new ArrayList<>();
        for (String s : split) {
            integers.add(Integer.valueOf(s));
        }

        //模板位置
        String templateFileName = printTemplatePath.concat("工单列表.xlsx");
//            String templateFileName = "/Users/fff/Downloads/print/工单列表.xlsx";
        //保存位置
        String fileName = "/service/excel/print/" + "工单列表" + System.currentTimeMillis() + ".xlsx";
//            String fileName = "/Users/fff/Downloads/print/" + "工单列表" + System.currentTimeMillis() + ".xlsx";
        /*//模板位置
        String templateFileName = "C:\\Users\\91045\\Desktop\\工单列表.xlsx";
        //保存位置
        String fileName = "C:\\Users\\91045\\Desktop\\" + "工单列表" + System.currentTimeMillis() + ".xlsx";
*/
        ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
        WriteSheet writeSheet = EasyExcel.writerSheet(1).build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

        WorkOrderDetailPrintModel wd = new WorkOrderDetailPrintModel();
        List<WorkOrderDetailPrintModel> list = new ArrayList<>();
        for (Integer id : integers) {
            WorkOrderDetailPrintModel wo = workOrderService.getBaseMapper().getModelData(id);
            if (wo.getState().equals("0")) {
                wo.setState("未开始");
            } else if (wo.getState().equals("1")) {
                wo.setState("执行中");
            } else if (wo.getState().equals("2")) {
                wo.setState("已结束");
            } else {
                wo.setState("已取消");
            }
            Integer loginUserId = LoginUtil.getLoginUserId();
            User user = userService.getById(loginUserId);
            wd.setHandleName(user.getName());
            wd.setHandleTime(new Date());
            BigDecimal unFinishNum = wo.getPlanNum().subtract(wo.getGoodNum());
            wo.setUnFinishNum(unFinishNum);
            list.add(wo);
        }
        excelWriter.fill(wd, writeSheet);
        excelWriter.fill(list, fillConfig, writeSheet);
        excelWriter.finish();
        File file = new File(fileName);
        OwnUtil.fileToResponse(file, response);
    }


    @UserLoginToken
    @ApiOperation(value = "工单生产任务从模版中添加 参数只传id")
    @RequestMapping(value = "from_model", method = RequestMethod.POST)
    public ResponseData fromModel(@RequestBody IdVo vo) {

        // 根据产品获取工艺路线
        if (Objects.nonNull(vo.getProductId())) {
            Product product = productService.getById(vo.getProductId());
            if (Objects.isNull(product.getProcessRouteId())) {
                return ResponseData.success(Collections.emptyList());
            }
            vo.setId(product.getProcessRouteId());
        }
        List<WOMissionResp> missionResps = new ArrayList<>();
        ProcessRoute pr = processRouteService.getById(vo.getId());
        if (pr != null) {
            if (StringUtil.isNotBlank(pr.getProcessList())) {
                JSONArray jsonArray = JSONArray.parseArray(pr.getProcessList());
                List<ProcessRoteProcessVo> list = jsonArray.toJavaList(ProcessRoteProcessVo.class);
                if (!CollectionUtils.isEmpty(list)) {
                    list.forEach(l -> {
                        WOMissionResp wmr = new WOMissionResp();
                        wmr.setId(l.getId());
                        wmr.setOrder(l.getOrder());
                        wmr.setProcessCode(l.getCode());
                        wmr.setProcessName(l.getName());
                        Processes p = processesService.getOne(new QueryWrapper<Processes>().eq("code", l.getCode()));
                        if (Objects.nonNull(p) && StringUtil.isNotBlank(p.getPermissions())) {
                            if (p.getPermissionsName().contains("所有人")) {
                                wmr.setPermissionsName("所有人");
                            } else {
                                List<String> permission = processesService.getBaseMapper().getProcessPermissionsUserName(p.getId());
                                wmr.setPermissionsName(permission.stream().map(String::valueOf).collect(Collectors.joining(",")));
                            }
                            wmr.setPermission(p.getPermissions());
                        }
                        if (Objects.nonNull(p) && StringUtils.hasLength(p.getOther())) {
                            wmr.setCustomFieldVos(JSONUtil.parseArray(p.getOther()).toList(CustomFieldVo.class));
                        }

                        wmr.setRate(l.getRate());
                        wmr.setPlanedNumber(BigDecimal.valueOf(0));
                        if (Objects.nonNull(p) && StringUtil.isNotBlank(p.getBadProduct())) {
                            List<String> bpList = badProductService.getBaseMapper().getCodeAndNameById(Arrays.asList(p.getBadProduct().split(",")));
                            if (!CollectionUtils.isEmpty(bpList)) {
                                wmr.setBadProductList(bpList.stream().map(String::valueOf).collect(Collectors.joining(",")));
                            }
                        }
                        wmr.setPlanedStartTime(TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, TimeUtil.getDayEarlyTime()));
                        wmr.setPlanedEndTime(TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, TimeUtil.getDayLateTime()));
                        missionResps.add(wmr);
                    });
                }
            }
        }
        return ResponseData.success(missionResps);
    }


    @UserLoginToken
    @ApiOperation(value = "工单批量操作 参数ids&type  type:begin/suspend/stop/cancel/del")
    @RequestMapping(value = "wos_handle", method = RequestMethod.POST)
    public ResponseData wosHandle(@RequestBody Map<String, String> map) {
        if (map != null && map.get("ids") != null) {

            List<String> ids = Arrays.asList(map.get("ids").split(","));
            String optionType = map.get("type");
            HandleNumResp hnr = new HandleNumResp();
            List<WorkOrder> workOrderList = workOrderService.listByIds(ids);
            Date date = new Date();
            if (!CollectionUtils.isEmpty(workOrderList)) {
                int success = 0;
                int fail = 0;

                if ("del".equals(optionType)) {
                    // 工单Codes
                    List<String> workOrderCodes = workOrderList.stream().map(WorkOrder::getCode).collect(Collectors.toList());
                    // 任务
                    List<Mission> missions = missionService.list(new LambdaQueryWrapper<Mission>().in(Mission::getWorkOrderCode, workOrderCodes));
                    // 删除销售详情
                    formTableDetailService.remove(new LambdaQueryWrapper<FormTableDetail>().in(FormTableDetail::getWorkOrderCode, workOrderCodes));
                    // 删除工单
                    workOrderService.removeByIds(ids);
                    success = workOrderCodes.size();
                    if (!CollectionUtils.isEmpty(missions)) {
                        missions.forEach(m -> {
                            List<WorkReport> workReports = workReportService.list(new QueryWrapper<WorkReport>().eq("mission_id", m.getId()));
                            if (!CollectionUtils.isEmpty(workReports)) {
                                // 同时纠正产品库存
                                if (m.getLast() == 0) {
                                    BigDecimal difference = workReports.stream().filter(i -> i.getVerifyState() == 1).map(WorkReport::getGoodProductNumber).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                                    productService.rectifyStockByDifference(difference.negate(), m.getProductCode());
                                }
                                // 报工入库删除
                                stockMsgService.removeStockDetailBy(workReports.stream().map(i -> i.getId().toString()).collect(Collectors.toList()));
                                workReports.forEach(w -> {
                                    workReportService.removeById(w.getId());
                                    // 删除不良品项报工
                                    reportBadProductService.remove(new LambdaQueryWrapper<ReportBadProduct>().eq(ReportBadProduct::getWorkReportId, w.getId()));
                                    MongoUtils.deleteById(w.getId(), mongoTemplate, "workReport");
                                });
                            }

                        });
                        List<Integer> missionIds = missions.stream().map(Mission::getId).collect(Collectors.toList());
                        // 删除任务
                        missionService.removeByIds(missionIds);
                        workOrderCodes.forEach(i -> {
                            // 同步消除erp
                            PushOrderNumVo queryData = formTableService.getErpSalesInfo(i);
                            if (Objects.nonNull(queryData) && Objects.nonNull(queryData.getRemoteSaleId())) {
                                queryData.setStatus(2);
                                erpService.pushOrderNum(queryData);
                            }
                        });
                    }
                } else {
                    for (WorkOrder workOrder : workOrderList) {
                        if ("begin".equals(optionType)) { //开始
                            if (workOrder.getState() == 0) {
                                workOrder.setState(1);
                                workOrder.setActualStartTime(date);
                                success++;
                            } else {
                                fail++;
                            }
                        } else if ("suspend".equals(optionType)) { //撤回
                            //只有已结束 和执行中 可以撤回 直接撤回到上一个状态
                            if (workOrder.getState() == 2) {
                                // 同步消除erp
                                PushOrderNumVo queryData = formTableService.getErpSalesInfo(workOrder.getCode());
                                if (Objects.nonNull(queryData) && Objects.nonNull(queryData.getRemoteSaleId())) {
                                    queryData.setStatus(2);
                                    erpService.pushOrderNum(queryData);
                                }
                                workOrder.setActualEndTime(null);
                                workOrder.setState(1);
                                List<Mission> missisons = missionService.list(new QueryWrapper<Mission>().eq("work_order_code", workOrder.getCode()));
                                missisons.forEach(m -> {
                                    if (m.getGoodProductNumber().compareTo(BigDecimal.ZERO) != 0) {
                                        m.setProcessState(1);
                                    }
                                    if (m.getGoodProductNumber().compareTo(BigDecimal.ZERO) == 0) {
                                        m.setProcessState(0);
                                    }
                                    if (m.getPlanedNumber().compareTo(m.getGoodProductNumber()) == 0 && !(m.getGoodProductNumber().compareTo(BigDecimal.ZERO) == 0)) {
                                        m.setProcessState(2);
                                    }
                                    missionService.updateById(m);
                                });
                                success++;
                            } else if (workOrder.getState() == 1) {
                                workOrder.setActualStartTime(null);
                                workOrder.setState(0);
                                success++;
                            } else {
                                fail++;
                            }

                        } else if ("stop".equals(optionType)) { //结束
                            if (workOrder.getState() != 0 && workOrder.getState() != 1) {
                                fail++;
                            } else {
                                workOrder.setActualEndTime(date);
                                List<Mission> missionList = missionService.list(new QueryWrapper<Mission>().eq("work_order_code", workOrder.getCode()));
                                missionList.forEach(m -> {
                                    m.setProcessState(2);
                                    missionService.updateById(m);
                                });
                                workOrder.setState(2);
                                success++;
                                PushOrderNumVo queryData = formTableService.getErpSalesInfo(workOrder.getCode());
                                if (Objects.nonNull(queryData) && Objects.nonNull(queryData.getRemoteSaleId())) {
                                    queryData.setStatus(1).setFinishNum(workOrder.getActualNumber())/*.setSaleDetailId(formTableDetail.getId())*/;
                                    erpService.pushOrderNum(queryData);
                                }
                            }
                        } else if ("cancel".equals(optionType)) { //取消
                            if (workOrder.getState() == 1) {
                                workOrder.setState(3);
                                success++;
                            } else {
                                fail++;
                            }
                        }
                        workOrderService.updateById(workOrder);
                    }
                }
                hnr.setSuccessNum(success);
                hnr.setFailNum(fail);
                hnr.setTotal(ids.size());
                return ResponseData.success(hnr);
            }
        }
        return ResponseData.fail(500, "操作失败参数错误");
    }

    @UserLoginToken
    @ApiOperation(value = "批量审批")
    @RequestMapping(value = "updateState", method = RequestMethod.POST)
    public ResponseData updateState(@RequestBody NormalVo vo) {
        int i = 0;
        int j = 0;
        for (String id : Arrays.asList(vo.getIds().split(","))) {
            WorkReport workReport = workReportService.getById(Integer.valueOf(id));
            if (workReport == null) {
                continue;
            }
            workReport.setVerifyState(1);
            workReport.setVerifyTime(new Date());
            boolean b = workReportService.updateById(workReport);
            if (b) {
                i++;
            } else {
                j++;
            }
        }
        return ResponseData.success("success: " + i + " defeated: " + j);

    }


    @UserLoginToken
    @ApiOperation(value = "刷新绩效")
    @RequestMapping(value = "flashPerformance", method = RequestMethod.POST)
    public ResponseData flashPerformance(@RequestBody NormalVo vo) {
        List<WorkReport> list = workReportService.listByIds(Arrays.asList(vo.getIds().split(",")));
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(l -> {
                if (l.getWagesId() != null && l.getPricingMethod() != null) {
                    BigDecimal price = new BigDecimal(0);
                    Wages w = wagesService.getById(l.getWagesId());
//                    if (w != null && w.getPricing() == 1) {
//                        double min = TimeUtil.getDateSubMinutes(TimeUtil.getDateString(l.getReportStartTime(),
//                                TimeUtil.DEFAULT_DATE_FORMAT), TimeUtil.getDateString(l.getReportEndTime(), TimeUtil.DEFAULT_DATE_FORMAT));
//                        if (min <= 0) {
//                            price = BigDecimal.ZERO;
//                        } else {
//                            BigDecimal minPrice = w.getUnitPrice().divide(BigDecimal.valueOf(60), 2, BigDecimal.ROUND_DOWN);
//                            price = BigDecimal.valueOf(min).multiply(minPrice).setScale(2, BigDecimal.ROUND_DOWN);
//                        }
//                    } else if (w.getPricing() == 0) {
//                        price = l.getGoodProductNumber().multiply(w.getUnitPrice()).setScale(2, BigDecimal.ROUND_DOWN);
//                    }
                    l.setEstimateWage(price);
                    workReportService.updateById(l);
                }
            });
        }
        return ResponseData.success("success");
    }


    @UserLoginToken
    @ApiOperation(value = "分配列表下拉数据")
    @RequestMapping(value = "distributionListData")
    public ResponseData distributionListData(@RequestBody(required = false) BooleanQuery booleanQuery) {
        booleanQuery = Optional.ofNullable(booleanQuery).orElse(new BooleanQuery());
        ResponseData<List<NameVo>> listResponseData = departmentsService.getListResponseData(new NameVo(), booleanQuery);
        return listResponseData;
    }


    @UserLoginToken
    @ApiOperation(value = "筛选方案列表")
    @RequestMapping(value = "screen_plan_list", method = RequestMethod.POST)
    public ResponseData screenPlanList(@RequestBody TypeVo vo) {
        List<ScreenPlan> list = screenPlanService.list(new QueryWrapper<ScreenPlan>().eq("type", vo.getType()));
        List<ScreenPlan> listReturn = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(l -> {
                if (StringUtil.isNotBlank(l.getUserId())) {
                    List<Integer> ids = Arrays.stream(l.getUserId().split(",")).map(Integer::parseInt).collect(Collectors.toList());
                    if (ids.contains(LoginUtil.getLoginUserId()) || ids.contains(-1)) {
                        l.setIsValid(1);
                        listReturn.add(l);
                    } else if (LoginUtil.getLoginUserId().equals(l.getCreateUser())) {
                        l.setIsValid(0);
                        listReturn.add(l);
                    }
                    if (l.getUserId().contains("-1")) {
                        l.setUserId("-1");
                    }
                } else {
                    if (LoginUtil.getLoginUserId().equals(l.getCreateUser())) {
                        l.setIsValid(0);
                        listReturn.add(l);
                    }
                }
            });
        }
        return ResponseData.success(listReturn);
    }

    @UserLoginToken
    @ApiOperation(value = "移动端卡片设置编辑")
    @RequestMapping(value = "app_card", method = RequestMethod.POST)
    public ResponseData appCard(@RequestBody AppCardHandle vo) {
        JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(vo.getList()));
        RedisUtil.set("app_card", jsonArray);
        return ResponseData.success("success");
    }

    @UserLoginToken
    @ApiOperation(value = "移动端卡片设置回显")
    @RequestMapping(value = "app_card_mess", method = RequestMethod.POST)
    public ResponseData appCardMess() {
        List<AppCardVo> voList = new ArrayList<>();
        JSONArray jsonArray = (JSONArray) RedisUtil.get("app_card");
        if (jsonArray != null && !jsonArray.isEmpty()) {
            voList = jsonArray.toJavaList(AppCardVo.class);
        } else {
            voList.add(new AppCardVo("工单编号", "code", false));
            voList.add(new AppCardVo("产品名称", "productName", false));
            voList.add(new AppCardVo("计划时间", "startTime", false));
            voList.add(new AppCardVo("工单进度", "progress", false));
            voList.add(new AppCardVo("状态", "state", false));
            voList.add(new AppCardVo("计划数", "planedNumber", false));
            voList.add(new AppCardVo("良品数", "goodProductNumber", false));
            voList.add(new AppCardVo("不良品数", "badProductNumber", false));
            voList.add(new AppCardVo("实际时间", "actualStartTime", false));
            voList.add(new AppCardVo("工单进度条", "list", false));
        }
        return ResponseData.success(voList);
    }

    @H5LoginToken
    @ApiOperation(value = "表单创建 , type要传 0/1/2  销售订单/生产计划/装配工单 ")
    @RequestMapping(value = "form_create", method = RequestMethod.POST)
    public ResponseData formHandle(@RequestBody FormTable vo) throws ParseException {

        if (!CollectionUtils.isEmpty(vo.getFormTableDetails())) {
            //保存订单数据
            vo.setCreateTime(new Date());
            vo.setCreateUser(LoginUtil.getLoginUserId());
            FormTable ft = new FormTable();
            if (vo.getType() == 0) {
                String code = customNumberService.generator(1);
                if (code.equals("fail")) {
                    return ResponseData.fail(500, "流水号已用完，请手动输入");
                }
                ft.setCode(code);
            } else if (vo.getType() == 1) {
                String code = customNumberService.generator(2);
                if (code.equals("fail")) {
                    return ResponseData.fail(500, "流水号已用完，请手动输入");
                }
                ft.setCode(code);
            } else if (vo.getType() == 2) {
                String code = customNumberService.generator(3);
                if (code.equals("fail")) {
                    return ResponseData.fail(500, "流水号已用完，请手动输入");
                }
                ft.setCode(code);
            }
            SpringUtil.copyPropertiesIgnoreNull(vo, ft);
            formTableService.createForm(vo.getFormTableDetails(), ft);
            formTableService.save(ft);

            return ResponseData.success("success");
        }
        return ResponseData.fail(500, "参数错误");
    }


    @UserLoginToken
    @ApiOperation(value = "表单编辑")
    @RequestMapping(value = "form_update", method = RequestMethod.POST)
    public ResponseData sOUpdate(@RequestBody FormTable vo) throws ParseException {
        //判断产品列表是否为空
        if (!CollectionUtils.isEmpty(vo.getFormTableDetails())) {
            //删除就是新的集合不存在 老的集合存在 就是删除
            List<FormTableDetail> newFTD = vo.getFormTableDetails();
            FormTable ft = formTableService.getById(vo.getId());
            List<FormTableDetail> oldFTD = formTableDetailService.list(new QueryWrapper<FormTableDetail>().eq("form_table_code", ft.getCode()));
            //新集合中不被旧集合包含的元素
            List<Integer> oldPrIds = oldFTD.stream().map(FormTableDetail::getProductId).collect(Collectors.toList());
            List<FormTableDetail> insertReduce = newFTD.stream().filter(item -> !oldPrIds.contains(item.getProductId())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(insertReduce)) {
                formTableService.createForm(insertReduce, ft);
            }
            //旧集合中不被新集合包含的元素 这里就是删除
            List<Integer> newPrIds = newFTD.stream().map(FormTableDetail::getProductId).collect(Collectors.toList());
            List<FormTableDetail> dleReduce = oldFTD.stream().filter(item -> !newPrIds.contains(item.getProductId())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(dleReduce)) {
                formTableService.dleForm(dleReduce);
            }
            for (FormTableDetail ftd : newFTD) {
                FormTableDetail f = formTableDetailService.getById(ftd.getId());
                SpringUtil.copyPropertiesIgnoreNull(ftd, f);
                WorkOrder wo = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", f.getWorkOrderCode()));
                wo.setPlanedNumber(f.getHandleNumber());
                workOrderService.updateById(wo);
                List<Mission> missions = missionService.list(new QueryWrapper<Mission>().eq("work_order_code", wo.getCode()));
                missions.forEach(m -> {
                    m.setPlanedNumber(f.getHandleNumber());
                    missionService.updateById(m);
                });
                formTableDetailService.updateById(f);
            }
            ft.setUpdateTime(new Date());
            ft.setUpdateUser(LoginUtil.getLoginUserId());
            formTableService.updateById(ft);
            return ResponseData.success("success");
        }
        return ResponseData.fail(500, "自定义表单产品不能为空");
    }


    @UserLoginToken
    @ApiOperation(value = "表单删除")
    @RequestMapping(value = "form_del", method = RequestMethod.POST)
    public ResponseData form_del(@RequestBody IdVo vo) {

        if (vo.getId() != null) {
            FormTable ft = formTableService.getById(vo.getId());
            List<FormTableDetail> fTD = formTableDetailService.list(new QueryWrapper<FormTableDetail>().eq("form_table_code", ft.getCode()));
            // 同步消除erp
            if (Objects.nonNull(ft.getRemoteSaleId())) {
                fTD.forEach(i -> {
                    PushOrderNumVo queryData = new PushOrderNumVo().setSaleId(ft.getId()).setRemoteSaleId(ft.getRemoteSaleId())
                            .setSaleDetailId(i.getId()).setStatus(2).setFinishNum(i.getHandleNumber())/*.setSaleDetailId(formTableDetail.getId())*/;
                    erpService.pushOrderNum(queryData);
                });
            }
            formTableService.dleForm(fTD);
            formTableService.removeById(vo.getId());
            return ResponseData.success("success");
        }
        return ResponseData.fail(500, "参数错误");
    }


    @UserLoginToken
    @ApiOperation(value = "表单列表")
    @RequestMapping(value = "form_list", method = RequestMethod.POST)
    public ResponseData formList(@RequestBody NormalVo vo) {

        Integer userId = LoginUtil.getLoginUserId();
        // 获取自定义排序
        String sort = (Optional.ofNullable(redisTemplate.opsForValue().get("motong:gongdan:formTable:Sort:" + userId)).orElse("DESC") + "");
        if (StringUtils.hasLength(vo.getSort())) {
            redisTemplate.opsForValue().set("motong:gongdan:formTable:Sort:" + userId, vo.getSort());
        }
        vo.setSort(Optional.ofNullable(vo.getSort()).orElse(sort));

        IPage<FormTable> resp = formTableService.getBaseMapper().getList(new Page<>(vo.getPage(), vo.getLimit()),
                new QueryWrapper<FormTable>().eq("type", vo.getType())
                        .like(StringUtil.isNotBlank(vo.getCode()), "code", vo.getCode())
                        .orderBy(StringUtils.hasLength(vo.getSort()), "ASC".equals(vo.getSort()), vo.getOrderBy()));
        if (!CollectionUtils.isEmpty(resp.getRecords())) {
            resp.getRecords().forEach(r -> {
                if (r.getCreateUser() != null) {
                    User user = userService.getById(r.getCreateUser());
                    r.setCreateName(user.getName());
                }
                if (r.getUpdateUser() != null) {
                    User user = userService.getById(r.getUpdateUser());
                    r.setUpdateName(user.getName());
                }
                if (r.getType() == 0 || r.getType() == 2) {
                    List<FormTableDetail> list = Optional.ofNullable(formTableDetailService.list(new QueryWrapper<FormTableDetail>()
                            .eq("form_table_code", r.getCode()))).orElse(Collections.emptyList());
                    r.setWorkOrderNum(!CollectionUtils.isEmpty(list) ? list.size() : 0);
                    if (r.getWorkOrderNum() != 0) {
                        List<WorkOrder> workOrderList = Optional.ofNullable(workOrderService.list(new QueryWrapper<WorkOrder>()
                                .in("code", list.stream().map(FormTableDetail::getWorkOrderCode).collect(Collectors.toList()))
                                .eq("state", 2))).orElse(Collections.emptyList());
                        r.setEndWorkOrder(!CollectionUtils.isEmpty(workOrderList) ? workOrderList.size() : 0);
                        BigDecimal totalPlanNum = list.stream().map(FormTableDetail::getHandleNumber).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                        r.setTotalPlanNum(totalPlanNum);
                    } else {
                        r.setEndWorkOrder(0);
                        r.setTotalPlanNum(BigDecimal.ZERO);
                    }
                    if (r.getWorkOrderNum() == 0) {
                        r.setRate(BigDecimal.ZERO);
                    } else {
                        r.setRate(BigDecimal.valueOf(r.getEndWorkOrder()).divide(BigDecimal.valueOf(r.getWorkOrderNum()), 2, RoundingMode.DOWN));
                    }
                }
            });
        }
        return ResponseData.success(resp);
    }

    @UserLoginToken
    @ApiOperation(value = "表单详情")
    @RequestMapping(value = "form_detail", method = RequestMethod.POST)
    public ResponseData<FormTable> formDetail(@RequestBody IdVo vo) {
        FormTable ft = formTableService.getById(vo.getId());
        List<FormTableDetail> ftd = formTableDetailService.list(new QueryWrapper<FormTableDetail>().eq("form_table_code", ft.getCode()));

        Map<String, BigDecimal> workCodeNumMap = new HashMap<>();
        if (Objects.nonNull(ftd) && !ftd.isEmpty()) {
            Set<String> workCodes = ftd.stream().map(FormTableDetail::getWorkOrderCode).collect(Collectors.toSet());
            if (!workCodes.isEmpty()) {
                workCodeNumMap = formTableDetailService.goodNumGroupByWorkCodes(workCodes);
            }
        }

        for (FormTableDetail formTableDetail : ftd) {
            Product pr = productService.getOne(new QueryWrapper<Product>().eq("id", formTableDetail.getProductId()));
            formTableDetail.setProductCode(pr.getCode());
            formTableDetail.setProductName(pr.getName());
            formTableDetail.setSpecification(pr.getSpecification());
            formTableDetail.setAttribute(pr.getAttribute());
            Unit unit = unitService.getById(pr.getUnitId());
            formTableDetail.setUnit(unit.getName());
            formTableDetail.setFinishNum(BigDecimal.ZERO);
            WorkOrder workOrder = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", formTableDetail.getWorkOrderCode()));
            if (Objects.nonNull(workOrder)) {
                if (Objects.nonNull(workCodeNumMap) && !workCodeNumMap.isEmpty()) {
                    formTableDetail.setFinishNum(Optional.ofNullable(workCodeNumMap.get(workOrder.getCode())).orElse(BigDecimal.ZERO));
                }
                formTableDetail.setWorkOrderId(workOrder.getId());
                formTableDetail.setState(workOrder.getState());
                formTableDetail.setBadProduct(workOrder.getBadProductNumber());
                // 放进开始结束时间
                formTableDetail.setStartTime(workOrder.getStartTime());
                formTableDetail.setEndTime(workOrder.getEndTime());
                if (StringUtil.isNotBlank(workOrder.getProcessId())) {
                    List<String> ids = Arrays.asList(workOrder.getProcessId().split(","));
                    List<WOProcessListResp> list = processesService.getBaseMapper().getWorkOrderProcessByIds(ids, workOrder.getCode());
                    formTableDetail.setList(list);
                }
                if (StringUtil.isNotBlank(workOrder.getOther())) {
                    formTableDetail.setCustomFieldVos(customFieldService.handleCustomFieldForList(workOrder.getOther()));
                }
            }
        }
        ft.setFormTableDetails(ftd);
        return ResponseData.success(ft);

    }


    @UserLoginToken
    @ApiOperation(value = "编辑销售订单")
    @PostMapping("editSalesOrder")
    @Transactional(rollbackFor = Exception.class)
    public ResponseData<String> editSalesOrder(@RequestBody EditSalesOrderVo vo) {
        boolean isUpdate = Objects.nonNull(vo.getId());
        Integer loginUserId = LoginUtil.getLoginUserId();
        FormTable formTable = new FormTable();
        BeanUtils.copyProperties(vo, formTable);
        formTable.setUpdateTime(new Date()).setUpdateUser(LoginUtil.getLoginUserId()).setType(0);
        int workerOrderIndex = 1;
        if (!StringUtils.hasLength(vo.getCode())) {
            String code = customNumberService.generator(1);
            if ("fail".equals(code)) {
                return ResponseData.fail(500, "流水号已用完，请手动输入");
            }
            formTable.setCode(code);
        }
        if (formTableService.count(new LambdaQueryWrapper<FormTable>().eq(FormTable::getCode, formTable.getCode()).ne(isUpdate, FormTable::getId, vo.getId())) > 0) {
            return ResponseData.fail(500, "表单编号已存在");
        }
        if (!isUpdate) {
            formTable.setCreateTime(new Date()).setCreateUser(loginUserId);
        } else {
            FormTable oriFormTable = formTableService.getById(vo.getId());
            // 获取当前编号的位置
            FormTableDetail lastOne = formTableDetailService.getOne(new LambdaQueryWrapper<FormTableDetail>().eq(FormTableDetail::getFtCode, oriFormTable.getCode()).orderByDesc(FormTableDetail::getId).last("LIMIT 1"));
            workerOrderIndex = Objects.isNull(lastOne) ? 1 : Integer.parseInt(lastOne.getWorkOrderCode().substring(lastOne.getWorkOrderCode().length() - 1)) + 1;
//            workerOrderIndex = formTableDetailService.count(new LambdaQueryWrapper<FormTableDetail>().eq(FormTableDetail::getFtCode, oriFormTable.getCode())) + 1;
            // 修改销售单编码
            if (!oriFormTable.getCode().equals(vo.getCode())) {
                formTableDetailService.update(new LambdaUpdateWrapper<FormTableDetail>().eq(FormTableDetail::getFtCode, oriFormTable.getCode()).set(FormTableDetail::getFtCode, vo.getCode()));
            }
        }
        formTableService.saveOrUpdate(formTable);
        vo.setId(formTable.getId());
        //执行销售单内商品删除操作
        if (Objects.nonNull(vo.getDelDetailIds()) && !vo.getDelDetailIds().isEmpty()) {
            formTableService.delProduct(vo.getDelDetailIds());
        }
        //保存或添加销售订单信息
        if (Objects.nonNull(vo.getSalesOrderProductVo()) && !vo.getSalesOrderProductVo().isEmpty()) {
            List<EditSalesOrderProductVo> salesOrderProductVo = vo.getSalesOrderProductVo();
            //分类商品的更新或添加
            Map<String, List<EditSalesOrderProductVo>> saveOrUpdateGroup = salesOrderProductVo.stream().collect(Collectors.groupingBy(i -> Objects.nonNull(i.getId()) ? "update" : "save"));
            // 执行内部商品类的保存操作
            formTableService.saveProduct(saveOrUpdateGroup.get("save"), formTable.getCode(), workerOrderIndex);
            // 执行内部商品类的更新操作
            formTableService.updateProduct(saveOrUpdateGroup.get("update"));
        }
        return ResponseData.success(isUpdate ? "修改成功!" : "添加成功");

    }


    @UserLoginToken
    @ApiOperation(value = "表单内添加产品列表")
    @RequestMapping(value = "form_product", method = RequestMethod.POST)
    public ResponseData formProduct(@RequestBody NormalVo vo) {
        IPage<Product> data = productService.page(new Page<>(vo.getPage(), vo.getLimit()),
                new QueryWrapper<Product>()
                        .like(StringUtil.isNotBlank(vo.getCode()), "code", vo.getCode()).or()
                        .like(StringUtil.isNotBlank(vo.getCode()), "name", vo.getCode()).or()
                        .like(StringUtil.isNotBlank(vo.getCode()), "specification", vo.getCode())
                        .orderByDesc("id"));
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            data.getRecords().forEach(d -> {
                if (d.getUnitId() != null) {
                    Unit unit = unitService.getById(d.getUnitId());
                    d.setUnitName(unit.getName());
                }
            });
        }
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation(value = "导入产品以及其他模块自定义数据返回整合数据 (type 所属模块 0 出入库 1 为销售订单模块)")
    @RequestMapping(value = "getByImportCode", method = RequestMethod.POST)
    public ResponseData<?> getByCode(MultipartFile file, @RequestParam(required = false) Integer type, @RequestParam(required = false, defaultValue = "0") Integer moduleType) {
        try (InputStream inputStream = file.getInputStream()) {
            ExcelReader reader = ExcelUtil.getReader(inputStream);

            // 读取第一列判断模板是否匹配
            List<List<Object>> headerList = reader.read(1, 1);
            if (Objects.nonNull(headerList) && !headerList.isEmpty()) {
                if (!"产品编号".equals(headerList.get(0).get(0).toString())) {
                    return ResponseData.fail(500, "模版不匹配");
                }
            }
            // 读取Excel数据
            List<Map<String, Object>> excelMapLists = reader.read(1, 2, Integer.MAX_VALUE);
            // 错误数量
            AtomicReference<Integer> errNum = new AtomicReference<>(0);
            //失败数据
            List<GetByImportCodeFailsVo> fails = new ArrayList<>();
            //获取自定义类别数据集合
            ColumnUtils columnUtils = new ColumnUtils(customFieldService, moduleType == 1 ? "workOrder" : "stockMsg");
            if (Objects.nonNull(excelMapLists) && !excelMapLists.isEmpty()) {
                excelMapLists.forEach(i -> {
                    String productCode = Optional.ofNullable(i.get("产品编号")).orElse("").toString();
                    String productName = Optional.ofNullable(i.get("产品名称")).orElse("").toString();
                    String specification = Optional.ofNullable(i.get("产品规格")).orElse("").toString();
                    if (!StringUtils.hasLength(productCode) && !StringUtils.hasLength(productName) && !StringUtils.hasLength(specification)) {
                        errNum.getAndSet(errNum.get() + 1);
                        fails.add(new GetByImportCodeFailsVo().setReason("产品编号、名称与规格不能同时为空"));
                        return;
                    }
                    String searchColumn = "productCode";
                    if (StringUtils.hasLength(productCode)) {
                        i.put(searchColumn, StringUtils.trimWhitespace(productCode));
                    } else if (StringUtils.hasLength(productName)) {
                        searchColumn = "productName";
                        i.put(searchColumn, StringUtils.trimWhitespace(productName));
                    } else if (StringUtils.hasLength(specification)) {
                        searchColumn = "specification";
                        i.put(searchColumn, StringUtils.trimWhitespace(specification));
                    }
                    i.put("searchColumn", searchColumn);
                    // 处理自定义字段
                    List<CustomFieldVo> customFieldVos = columnUtils.cnGetCuColumnsString(i);
                    i.put("customFieldVos", customFieldVos);
                });
                System.out.println("执行完毕");
                Map<String, List<Map<String, Object>>> searchColumn = excelMapLists.stream().filter(i -> Objects.nonNull(i.get("searchColumn"))).collect(Collectors.groupingBy(i -> i.get("searchColumn").toString()));
                List<List<Map<String, Object>>> columnData = new ArrayList<>(searchColumn.size());
                searchColumn.forEach((k, v) -> columnData.add(v));
                Map<String, Object> returnData = this.reloadData(columnData, errNum, fails);
                return ResponseData.success(returnData);
            }
            return ResponseData.success(Collections.emptyList());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseData.fail(500, "导入失败!");

    }

    /**
     * 整合数据
     *
     * @param columnData 列数据集合
     * @param errNum     错误数量
     * @param fails      失败详情
     * @return 整合后的数据包含 成功数据 失败次数 失败数据原因
     */
    private Map<String, Object> reloadData(List<List<Map<String, Object>>> columnData, AtomicReference<Integer> errNum, List<GetByImportCodeFailsVo> fails) {
        Map<String, String> scColumnMap = new HashMap<>();
        scColumnMap.put("productCode", "code");
        scColumnMap.put("productName", "name");
        scColumnMap.put("specification", "specification");
        Map<String, Map<String, List<Product>>> columnProducts = productService.getColumnProductsByScColumn(columnData, scColumnMap);
        List<GetByImportCodeDataVo> data = new ArrayList<>();
        columnData.forEach(
                i -> {
                    if (!i.isEmpty()) {
                        String searchColumn = i.get(0).get("searchColumn").toString();
                        Map<String, List<Product>> productsGroup = columnProducts.get(searchColumn);
                        for (Map<String, Object> item : i) {
                            String searchDataData = item.get(searchColumn).toString();
                            List<Product> products = productsGroup.get(searchDataData);
                            List<GetByImportCodeDataVo> finalData = new ArrayList<>();
                            if (Objects.isNull(products)) {
                                GetByImportCodeFailsVo getByImportCodeFailsVo = new GetByImportCodeFailsVo();
                                switch (searchColumn) {
                                    case "productCode":
                                        getByImportCodeFailsVo.setProductCode(searchDataData);
                                        break;
                                    case "productName":
                                        getByImportCodeFailsVo.setProductName(searchDataData);
                                        break;
                                    default:
                                        getByImportCodeFailsVo.setSpecification(searchDataData);
                                }
                                fails.add(getByImportCodeFailsVo);
                                errNum.getAndSet(errNum.get() + 1);
                            } else {
                                // 自定义字段过滤
                                products.forEach(d -> {
                                    GetByImportCodeDataVo getByImportCodeDataVo = new GetByImportCodeDataVo();
                                    BeanUtils.copyProperties(d, getByImportCodeDataVo);
                                    //添加销售订单模块三个字段
                                    getByImportCodeDataVo.setPlanedNumber(Convert.toBigDecimal(item.getOrDefault("数量", "0")));
                                    getByImportCodeDataVo.setStartTime(item.get("开始时间") + "");
                                    getByImportCodeDataVo.setEndTime(item.get("结束时间") + "");
                                    finalData.add(getByImportCodeDataVo);
                                });
                                finalData.forEach(d -> d.setCustomFieldVos((List<CustomFieldVo>) item.get("customFieldVos")));
                                data.addAll(finalData);
                            }
                        }
                    }
                }
        );
        Map<String, Object> returnData = new HashMap<>(3);
        returnData.put("errNum", errNum);
        returnData.put("successData", data);
        returnData.put("failData", fails);
        return returnData;

    }

    @UserLoginToken
    @ApiOperation("修改加急状态")
    @PostMapping("urgent")
    public ResponseData<?> urgent(@RequestBody IdValueQuery param) {
        if (Objects.isNull(param.getIds())) {
            return ResponseData.fail("必要参数不能为空!");
        }
        List<String> ids = Arrays.asList(param.getIds().split(","));
        workOrderService.update(new LambdaUpdateWrapper<WorkOrder>().in(WorkOrder::getId, ids).set(WorkOrder::getIsUrgent, param.getValue()));
        return ResponseData.success(String.format("加急共操作%d条，成功%d条，失败0条。", ids.size(), ids.size()));
    }


}
